import * as fs from "node:fs";
import checkDiskSpace from 'check-disk-space'
import { Controller, Delete, Get, Module, Param, Put, Query, Request, UseInterceptors } from "@nestjs/common";
import { PrismaClient } from "@prisma/client";
import { WebResult } from "src/common/web.result";
import { ResourceService, ResourceType } from "src/resource/resource.service";
import { ResourceModule } from "src/resource/resource.module";
import { FastifyRequest } from "fastify";
import { AdminLoginInterceptor } from "src/admin/interceptor/alogin.interceptor";
import { UserTokenService } from "src/user/token.service";
import { UserModule } from "src/user/user.module";
import configuration from "src/common/configuration";

@Controller("/admin/resource")
@UseInterceptors(AdminLoginInterceptor)
export class AdminResourceController {
  constructor(
    private readonly prisma: PrismaClient,
    private readonly userTokenService: UserTokenService,
    private readonly resourceService: ResourceService,
  ) {}

  @Get(["/disk", "/disk/info"])
  async getDiskInformation() {
    const info = await checkDiskSpace(configuration.resource.rootDirectoryPath);
    info.diskPath = undefined;
    return WebResult.success(info);
  }

  /**
   * 清理掉不存在的资源
   * @returns WebResult
   */
  @Put("/refresh")
  async refresh() {
    try {
      const resources = await this.prisma.resource.findMany();
      for (const r of resources) {
        const mimeType = r.mime_type;
        const resourceType =
          this.resourceService.getResourceTypeByMIMEType(mimeType);
        const filePath = this.resourceService.getResourceSavePath(
          r.uploader_id,
          r.name,
          resourceType,
        );
        if (!fs.existsSync(filePath)) {
          this.prisma.resource
            .delete({
              where: {
                id: r.id,
              },
            })
            .then();
        }
      }
      return WebResult.success(undefined, "正在运行刷新任务");
    } catch (e) {
      console.error(e);
      return WebResult.failure(undefined, "内部错误");
    }
  }

  @Get("/list")
  async list() {
    const rows = await this.prisma.resource.findMany({
      include: {
        user: {
          select: {
            nickname: true,
          },
        },
      },
    });
    return WebResult.success(rows);
  }

  @Get(["/has/:type/:name", "/has/:type/:uid/:name"])
  async hasResource(
    @Param("uid") uid: string,
    @Param("type") resourceType: string,
    @Param("name") fileName: string,
  ) {
    if (!this.resourceService.isResourceType(resourceType)) {
      return WebResult.failure(undefined, "resource type is not valid");
    }
    const whereCondition = {
      name: fileName,
      type: resourceType,
    };
    if (uid) {
      const uploaderID = parseInt(uid);
      if (isNaN(uploaderID)) {
        whereCondition["uploader_id"] = uploaderID;
      }
    }
    try {
      const [r] = await this.prisma.resource.findMany({
        select: {
          id: true,
        },
        where: whereCondition,
        take: 1,
      });
      if (r) {
        return WebResult.success(true);
      }
      return WebResult.success(false);
    } catch (e) {
      console.error(e);
      return WebResult.failure(undefined, "内部错误");
    }
  }

  @Get(["/has/self/:type/:name", "/has/:type/self/:name"])
  hasSelfResource(
    @Request() request: FastifyRequest,
    @Param("type") resourceType: string,
    @Param("name") fileName: string,
  ) {
    const uid = this.userTokenService.getUserIDFromRequest(request);
    return this.hasResource(uid?.toString(), resourceType, fileName);
  }


  @Get("/count")
  async getResourceCount() {
    const count = await this.prisma.resource.count();
    return WebResult.success(count);
  }

  @Get("/page/:page")
  async getResourceByPage(
    @Param("page") page: string,
    @Query("pageSize") pageSize: string = "10",
) {
    const p = parseInt(page);
    const size = parseInt(pageSize);
    if (isNaN(p)) {
      return WebResult.failure(undefined, "page must be a number");
    }
    if (isNaN(size)) {
      return WebResult.failure(undefined, "pageSize must be a number");
    }
    const resources = await this.resourceService.getResourceByPage(p, size);
    return WebResult.success(resources);
  }

  @Delete(["/:id", "/delete/:id"])
  async deleteResourceByID(
    @Param("id") id: string
  ) {
    const resourceID = parseInt(id);
    if (isNaN(resourceID)) {
      return WebResult.failure(undefined, "resource id must be a number");
    }
    const r = await this.prisma.resource.findUnique({
      select: {
        uploader_id: true,
        name: true,
        type: true,
      },
      where: {
        id: resourceID,
      },
    });
    if (r) {
      const filePath = this.resourceService.getResourceSavePath(
        r.uploader_id,
        r.name,
        r.type as ResourceType
      );
      if (fs.existsSync(filePath)) {
        fs.rmSync(filePath);
      }
      if (fs.existsSync(filePath)) {
        return WebResult.failure(undefined, "删除失败");
      }
    } else {
      return WebResult.failure(undefined, "resource not found");
    }

    const rd = await this.prisma.resource.delete({
      where: {
        id: resourceID,
      }
    });
    if (rd) {
      return WebResult.success(undefined, "删除成功");
    }
    return WebResult.failure(undefined, "删除失败");
  }
}

@Module({
  imports: [UserModule, ResourceModule],
  controllers: [AdminResourceController],
})
export class AdminResourceModule {}
